﻿using System;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

namespace Cnblogs.Common
{
    // this code has been modified from the orginal code
    // from Kevin Marshall's post 
    // http://blogs.claritycon.com/kevinmarshall/2010/10/13/wp7-page-transitions-sample/
    // modify by alexis 20110523 change storyboard
    public class DialogService
    {
        private const string VeticalInStoryboard = @"
        <Storyboard  xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"">
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=""(UIElement.RenderTransform).(TranslateTransform.Y)"">                                           
                    <EasingDoubleKeyFrame KeyTime=""0"" Value=""-50""/>
                    <EasingDoubleKeyFrame KeyTime=""0:0:2"" Value=""0"">
                        <EasingDoubleKeyFrame.EasingFunction>
                            <ExponentialEase EasingMode=""EaseInOut"" Exponent=""6""/>
                        </EasingDoubleKeyFrame.EasingFunction>
                    </EasingDoubleKeyFrame>
                </DoubleAnimationUsingKeyFrames>
            <DoubleAnimation Storyboard.TargetProperty=""(UIElement.Opacity)"" From=""0"" To=""1"" Duration=""0:0:2"" 
                                 Storyboard.TargetName=""LayoutRoot"">
                <DoubleAnimation.EasingFunction>
                    <ExponentialEase EasingMode=""EaseOut"" Exponent=""6""/>
                </DoubleAnimation.EasingFunction>
            </DoubleAnimation>
        </Storyboard>";

        private const string VeticalOutStoryboard = @"
        <Storyboard  xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"">
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=""(UIElement.RenderTransform).(TranslateTransform.Y)"">                                           
                <EasingDoubleKeyFrame KeyTime=""0"" Value=""0""/>
                <EasingDoubleKeyFrame KeyTime=""0:0:2"" Value=""-50"">
                    <EasingDoubleKeyFrame.EasingFunction>
                        <ExponentialEase EasingMode=""EaseIn"" Exponent=""6""/>
                    </EasingDoubleKeyFrame.EasingFunction>
                </EasingDoubleKeyFrame>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimation Storyboard.TargetProperty=""(UIElement.Opacity)"" From=""1"" To=""0"" Duration=""0:0:2"" 
                                 Storyboard.TargetName=""LayoutRoot"">
                <DoubleAnimation.EasingFunction>
                    <ExponentialEase EasingMode=""EaseIn"" Exponent=""6""/>
                </DoubleAnimation.EasingFunction>
            </DoubleAnimation>
        </Storyboard>";

        private Panel _popupContainer;
        private Frame _rootVisual;
        private PhoneApplicationPage _page;
        private Panel _overlay;

        public FrameworkElement Child { get; set; }
        public double VerticalOffset { get; set; }
        public Brush BackgroundBrush { get; set; }

        internal bool IsOpen { get; set; }
        protected internal bool IsBackKeyOverride { get; set; }

        public event EventHandler Closed;
        //public event EventHandler Opened;

        // set this to prevent the dialog service from closing on back click
        public bool HasPopup { get; set; }

        internal PhoneApplicationPage Page
        {
            get { return _page ?? (_page = RootVisual.GetVisualDescendants().OfType<PhoneApplicationPage>().FirstOrDefault()); }
        }

        internal Frame RootVisual
        {
            get { return _rootVisual ?? (_rootVisual = Application.Current.RootVisual as Frame); }
        }

        internal Panel PopupContainer
        {
            get
            {
                if (_popupContainer == null)
                {
                    //rootvisual frame
                    _popupContainer = RootVisual.GetVisualDescendants().OfType<Panel>().First();
                }

                return _popupContainer;
            }
        }

        private void InitializePopup()
        {
            // Add overlay which is the size of RootVisual
            _overlay = new Grid { Name = Guid.NewGuid().ToString(), MaxHeight = 200,VerticalAlignment= VerticalAlignment.Top };
            if (Child != null)
            {
                Panel parent = VisualTreeHelper.GetParent(Child) as Panel;
                if (parent != null) parent.Children.Remove(Child);
                _overlay.Children.Add(Child);
            }
            if (BackgroundBrush != null)
                _overlay.Background = BackgroundBrush;

            _overlay.Margin = new Thickness(0, VerticalOffset, 0, 0);
            _overlay.Opacity = 0;

            // Initialize popup to draw the context menu over all controls
            if (PopupContainer != null)
            {
                Panel parent = VisualTreeHelper.GetParent(_overlay) as Panel;
                if (parent != null) parent.Children.Remove(_overlay);
                PopupContainer.Children.Add(_overlay);
            }
        }

        protected internal void SetAlignmentsOnOverlay(HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment)
        {
            if (_overlay != null)
            {
                _overlay.HorizontalAlignment = horizontalAlignment;
                _overlay.VerticalAlignment = verticalAlignment;
            }
        }

        private static readonly object Lockobj = new object();
        /// <summary>
        /// Shows the context menu.
        /// </summary>
        public void Show()
        {
            lock (Lockobj)
            {
                IsOpen = true;
                InitializePopup();
                Storyboard storyboard;
                storyboard = XamlReader.Load(VeticalInStoryboard) as Storyboard;
                _overlay.RenderTransform = new TranslateTransform();
                if (storyboard != null)
                {
                    RootVisual.Dispatcher.BeginInvoke(() =>
                    {
                        foreach (var t in storyboard.Children)
                            Storyboard.SetTarget(t, _overlay);

                        storyboard.Begin();

                    });
                }
            }
        }

        void OnNavigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
        {
            Hide();
        }

        public void Hide()
        {
            if (!IsOpen)
                return;

            Storyboard storyboard = XamlReader.Load(VeticalOutStoryboard) as Storyboard;
            _overlay.RenderTransform = new TranslateTransform();
            if (storyboard != null)
            {
                storyboard.Completed += _hideStoryboard_Completed;

                foreach (var t in storyboard.Children)
                    Storyboard.SetTarget(t, _overlay);

                storyboard.Begin();
            }
        }

        void _hideStoryboard_Completed(object sender, EventArgs e)
        {
            IsOpen = false;

            if (PopupContainer != null)
            {
                PopupContainer.Children.Remove(_overlay);
            }

            if (Closed != null)
                Closed(this, null);
        }

        public void OnBackKeyPress(object sender, CancelEventArgs e)
        {
            if (HasPopup)
            {
                e.Cancel = true;
                return;
            }

            if (IsOpen)
            {
                e.Cancel = true;
                Hide();
            }
        }
    }
}